"""
能耗分析和优化API端点
"""
from datetime import datetime, timedelta
from typing import List, Dict, Any
from fastapi import APIRouter, HTTPException, Depends, Query
from uuid import uuid4
import logging

from backend.schemas.energy_analysis import (
    EnergyAnalysisRequest, EnergyAnalysisResponse,
    EnergyOptimizationRequest, EnergyOptimizationResponse,
    EnergyReportRequest, EnergyReportResponse,
    EnergyStatisticsRequest, EnergyStatisticsResponse,
    EnergyComparisonRequest, EnergyComparisonResponse,
    EnergyTrendRequest, EnergyTrendResponse,
    EnergyAlertRequest, EnergyAlertResponse,
    EnergyDashboardRequest, EnergyDashboardResponse,
    EnergyType, OptimizationLevel, EnergyEfficiencyGrade
)
from backend.services.energy_analysis_service import EnergyAnalysisService

logger = logging.getLogger(__name__)

router = APIRouter(prefix="/energy-analysis", tags=["能耗分析"])

# 全局服务实例
energy_service = EnergyAnalysisService()


@router.post("/analyze", response_model=EnergyAnalysisResponse)
async def analyze_energy_consumption(request: EnergyAnalysisRequest):
    """
    分析能耗数据
    
    - **space_id**: 空间ID
    - **energy_types**: 要分析的能耗类型列表
    - **start_time**: 分析开始时间
    - **end_time**: 分析结束时间
    """
    try:
        logger.info(f"开始分析空间 {request.space_id} 的能耗数据")
        
        # 验证时间范围
        if request.end_time <= request.start_time:
            raise HTTPException(status_code=400, detail="结束时间必须晚于开始时间")\n        
        # 验证时间跨度不超过30天
        if (request.end_time - request.start_time).days > 30:
            raise HTTPException(status_code=400, detail="分析时间跨度不能超过30天")
        
        # 执行分析
        analysis_result = await energy_service.collect_and_analyze_energy_data(
            space_id=request.space_id,
            energy_types=request.energy_types,
            start_time=request.start_time,
            end_time=request.end_time
        )
        
        # 转换为响应格式
        response = EnergyAnalysisResponse(
            analysis_id=analysis_result.analysis_id,
            space_id=analysis_result.space_id,
            analysis_period=analysis_result.analysis_period,
            total_consumption=analysis_result.total_consumption,
            consumption_by_type=analysis_result.consumption_by_type,
            total_cost=analysis_result.total_cost,
            cost_by_type=analysis_result.cost_by_type,
            efficiency_grade=analysis_result.efficiency_grade,
            baseline_comparison=analysis_result.baseline_comparison,
            peak_consumption=analysis_result.peak_consumption,
            trends=analysis_result.trends,
            optimization_potential=analysis_result.optimization_potential
        )
        
        logger.info(f"能耗分析完成，分析ID: {analysis_result.analysis_id}")
        return response
        
    except Exception as e:
        logger.error(f"能耗分析失败: {str(e)}")
        raise HTTPException(status_code=500, detail=f"能耗分析失败: {str(e)}")


@router.post("/optimize", response_model=EnergyOptimizationResponse)
async def generate_optimization_recommendations(request: EnergyOptimizationRequest):
    """
    生成能耗优化建议
    
    - **analysis_id**: 分析结果ID
    """
    try:
        logger.info(f"为分析 {request.analysis_id} 生成优化建议")
        
        # 获取分析结果
        analysis_result = energy_service.analysis_results_storage.get(request.analysis_id)
        if not analysis_result:
            raise HTTPException(status_code=404, detail="分析结果不存在")
        
        # 生成优化建议
        recommendations = energy_service.generate_optimization_recommendations(analysis_result)
        
        # 计算总体统计
        total_energy_savings = sum(rec.estimated_savings.get('energy_kwh', 0) for rec in recommendations)
        total_cost_savings = sum(rec.estimated_savings.get('cost_yuan', 0) for rec in recommendations)
        total_co2_reduction = sum(rec.estimated_savings.get('co2_kg', 0) for rec in recommendations)
        total_implementation_cost = sum(rec.implementation_cost for rec in recommendations)
        average_payback_period = sum(rec.payback_period for rec in recommendations) / len(recommendations) if recommendations else 0
        
        # 转换为响应格式
        recommendation_responses = []
        for rec in recommendations:
            recommendation_responses.append({
                "recommendation_id": rec.recommendation_id,
                "space_id": rec.space_id,
                "energy_type": rec.energy_type,
                "optimization_level": rec.optimization_level,
                "title": rec.title,
                "description": rec.description,
                "estimated_savings": rec.estimated_savings,
                "implementation_cost": rec.implementation_cost,
                "payback_period": rec.payback_period,
                "priority": rec.priority,
                "actions": rec.actions
            })
        
        response = EnergyOptimizationResponse(
            recommendations=recommendation_responses,
            total_potential_savings={
                'energy_kwh': total_energy_savings,
                'cost_yuan': total_cost_savings,
                'co2_kg': total_co2_reduction
            },
            total_implementation_cost=total_implementation_cost,
            average_payback_period=average_payback_period
        )
        
        logger.info(f"生成了 {len(recommendations)} 条优化建议")
        return response
        
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"生成优化建议失败: {str(e)}")
        raise HTTPException(status_code=500, detail=f"生成优化建议失败: {str(e)}")


@router.post("/report", response_model=EnergyReportResponse)
async def generate_energy_report(request: EnergyReportRequest):
    """
    生成能耗报告
    
    - **report_type**: 报告类型 (daily/weekly/monthly/annual)
    - **start_time**: 报告开始时间
    - **end_time**: 报告结束时间
    - **spaces**: 包含的空间ID列表
    """
    try:
        logger.info(f"生成 {request.report_type} 能耗报告")
        
        # 验证时间范围
        if request.end_time <= request.start_time:
            raise HTTPException(status_code=400, detail="结束时间必须晚于开始时间")
        
        # 生成报告
        report = energy_service.generate_energy_report(
            report_type=request.report_type,
            period=(request.start_time, request.end_time),
            spaces=request.spaces
        )
        
        # 转换分析结果
        analysis_responses = []
        for result in report.analysis_results:
            analysis_responses.append(EnergyAnalysisResponse(
                analysis_id=result.analysis_id,
                space_id=result.space_id,
                analysis_period=result.analysis_period,
                total_consumption=result.total_consumption,
                consumption_by_type=result.consumption_by_type,
                total_cost=result.total_cost,
                cost_by_type=result.cost_by_type,
                efficiency_grade=result.efficiency_grade,
                baseline_comparison=result.baseline_comparison,
                peak_consumption=result.peak_consumption,
                trends=result.trends,
                optimization_potential=result.optimization_potential
            ))
        
        # 转换建议
        recommendation_responses = []
        for rec in report.recommendations:
            recommendation_responses.append({
                "recommendation_id": rec.recommendation_id,
                "space_id": rec.space_id,
                "energy_type": rec.energy_type,
                "optimization_level": rec.optimization_level,
                "title": rec.title,
                "description": rec.description,
                "estimated_savings": rec.estimated_savings,
                "implementation_cost": rec.implementation_cost,
                "payback_period": rec.payback_period,
                "priority": rec.priority,
                "actions": rec.actions
            })
        
        response = EnergyReportResponse(
            report_id=report.report_id,
            report_type=report.report_type,
            period=report.period,
            spaces=report.spaces,
            analysis_results=analysis_responses,
            recommendations=recommendation_responses,
            summary=report.summary,
            generated_at=report.generated_at
        )
        
        logger.info(f"能耗报告生成完成，报告ID: {report.report_id}")
        return response
        
    except Exception as e:
        logger.error(f"生成能耗报告失败: {str(e)}")
        raise HTTPException(status_code=500, detail=f"生成能耗报告失败: {str(e)}")


@router.post("/statistics", response_model=EnergyStatisticsResponse)
async def get_energy_statistics(request: EnergyStatisticsRequest):
    """
    获取能耗统计信息
    
    - **space_id**: 空间ID
    - **start_time**: 统计开始时间
    - **end_time**: 统计结束时间
    """
    try:
        logger.info(f"获取空间 {request.space_id} 的能耗统计")
        
        # 获取统计信息
        statistics = energy_service.get_energy_statistics(
            space_id=request.space_id,
            period=(request.start_time, request.end_time)
        )
        
        if 'error' in statistics:
            raise HTTPException(status_code=404, detail=statistics['error'])
        
        response = EnergyStatisticsResponse(**statistics)
        
        logger.info(f"能耗统计获取完成")
        return response
        
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"获取能耗统计失败: {str(e)}")
        raise HTTPException(status_code=500, detail=f"获取能耗统计失败: {str(e)}")


@router.get("/dashboard", response_model=EnergyDashboardResponse)
async def get_energy_dashboard(
    spaces: List[str] = Query(..., description="空间ID列表"),
    time_range: str = Query("24h", description="时间范围", regex="^(1h|6h|24h|7d|30d)$")
):
    """
    获取能耗仪表板数据
    
    - **spaces**: 空间ID列表
    - **time_range**: 时间范围 (1h/6h/24h/7d/30d)
    """
    try:
        logger.info(f"获取能耗仪表板数据，时间范围: {time_range}")
        
        # 计算时间范围
        end_time = datetime.now()
        time_deltas = {
            '1h': timedelta(hours=1),
            '6h': timedelta(hours=6),
            '24h': timedelta(days=1),
            '7d': timedelta(days=7),
            '30d': timedelta(days=30)
        }
        start_time = end_time - time_deltas[time_range]
        
        # 收集仪表板数据
        dashboard_data = {
            'dashboard_id': str(uuid4()),
            'spaces': spaces,
            'time_range': time_range,
            'real_time_data': {},
            'summary_statistics': {},
            'trend_charts': [],
            'efficiency_rankings': [],
            'active_alerts': [],
            'recommendations_preview': [],
            'generated_at': datetime.now()
        }
        
        # 为每个空间收集数据
        for space_id in spaces:
            try:
                # 获取统计信息
                stats = energy_service.get_energy_statistics(space_id, (start_time, end_time))
                if 'error' not in stats:
                    dashboard_data['real_time_data'][space_id] = {
                        'consumption': stats['total_consumption_kwh'],
                        'cost': stats['total_cost_yuan'],
                        'efficiency_grade': stats['average_efficiency_grade']
                    }
                    
                    # 添加到效率排名
                    dashboard_data['efficiency_rankings'].append({
                        'space_id': space_id,
                        'efficiency_grade': stats['average_efficiency_grade'],
                        'consumption': stats['total_consumption_kwh']
                    })
            except Exception as e:
                logger.warning(f"获取空间 {space_id} 数据失败: {str(e)}")
        
        # 计算汇总统计
        total_consumption = sum(data.get('consumption', 0) for data in dashboard_data['real_time_data'].values())
        total_cost = sum(data.get('cost', 0) for data in dashboard_data['real_time_data'].values())
        
        dashboard_data['summary_statistics'] = {
            'total_spaces': len(spaces),
            'total_consumption_kwh': round(total_consumption, 2),
            'total_cost_yuan': round(total_cost, 2),
            'average_consumption_per_space': round(total_consumption / len(spaces), 2) if spaces else 0
        }
        
        # 按效率排序
        dashboard_data['efficiency_rankings'].sort(key=lambda x: x['efficiency_grade'], reverse=True)
        
        response = EnergyDashboardResponse(**dashboard_data)
        
        logger.info(f"能耗仪表板数据获取完成")
        return response
        
    except Exception as e:
        logger.error(f"获取能耗仪表板失败: {str(e)}")
        raise HTTPException(status_code=500, detail=f"获取能耗仪表板失败: {str(e)}")


@router.get("/types", response_model=List[str])
async def get_energy_types():
    """获取支持的能耗类型列表"""
    return [energy_type.value for energy_type in EnergyType]


@router.get("/efficiency-grades", response_model=List[str])
async def get_efficiency_grades():
    """获取能效等级列表"""
    return [grade.value for grade in EnergyEfficiencyGrade]


@router.get("/optimization-levels", response_model=List[str])
async def get_optimization_levels():
    """获取优化级别列表"""
    return [level.value for level in OptimizationLevel]


@router.get("/analysis/{analysis_id}", response_model=EnergyAnalysisResponse)
async def get_analysis_result(analysis_id: str):
    """
    获取指定的分析结果
    
    - **analysis_id**: 分析ID
    """
    try:
        analysis_result = energy_service.analysis_results_storage.get(analysis_id)
        if not analysis_result:
            raise HTTPException(status_code=404, detail="分析结果不存在")
        
        response = EnergyAnalysisResponse(
            analysis_id=analysis_result.analysis_id,
            space_id=analysis_result.space_id,
            analysis_period=analysis_result.analysis_period,
            total_consumption=analysis_result.total_consumption,
            consumption_by_type=analysis_result.consumption_by_type,
            total_cost=analysis_result.total_cost,
            cost_by_type=analysis_result.cost_by_type,
            efficiency_grade=analysis_result.efficiency_grade,
            baseline_comparison=analysis_result.baseline_comparison,
            peak_consumption=analysis_result.peak_consumption,
            trends=analysis_result.trends,
            optimization_potential=analysis_result.optimization_potential
        )
        
        return response
        
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"获取分析结果失败: {str(e)}")
        raise HTTPException(status_code=500, detail=f"获取分析结果失败: {str(e)}")


@router.get("/recommendations/{space_id}", response_model=List[Dict[str, Any]])
async def get_space_recommendations(space_id: str):
    """
    获取指定空间的所有优化建议
    
    - **space_id**: 空间ID
    """
    try:
        recommendations = []
        for rec in energy_service.recommendations_storage.values():
            if rec.space_id == space_id:
                recommendations.append({
                    "recommendation_id": rec.recommendation_id,
                    "space_id": rec.space_id,
                    "energy_type": rec.energy_type.value,
                    "optimization_level": rec.optimization_level.value,
                    "title": rec.title,
                    "description": rec.description,
                    "estimated_savings": rec.estimated_savings,
                    "implementation_cost": rec.implementation_cost,
                    "payback_period": rec.payback_period,
                    "priority": rec.priority,
                    "actions": rec.actions
                })
        
        # 按优先级排序
        recommendations.sort(key=lambda x: x['priority'])
        
        return recommendations
        
    except Exception as e:
        logger.error(f"获取空间建议失败: {str(e)}")
        raise HTTPException(status_code=500, detail=f"获取空间建议失败: {str(e)}")


@router.delete("/analysis/{analysis_id}")
async def delete_analysis_result(analysis_id: str):
    """
    删除分析结果
    
    - **analysis_id**: 分析ID
    """
    try:
        if analysis_id not in energy_service.analysis_results_storage:
            raise HTTPException(status_code=404, detail="分析结果不存在")
        
        del energy_service.analysis_results_storage[analysis_id]
        
        # 同时删除相关的建议
        recommendations_to_delete = []
        for rec_id, rec in energy_service.recommendations_storage.items():
            # 这里需要根据实际的关联关系来判断
            # 暂时跳过，因为建议和分析结果的关联关系需要在服务中维护
            pass
        
        return {"message": "分析结果删除成功"}
        
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"删除分析结果失败: {str(e)}")
        raise HTTPException(status_code=500, detail=f"删除分析结果失败: {str(e)}")